package fun.huixi.weiju.business.impl;


import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import fun.huixi.weiju.business.AppealBusiness;
import fun.huixi.weiju.exception.BusinessException;
import fun.huixi.weiju.page.PageData;
import fun.huixi.weiju.pojo.dto.appeal.PageQueryAppealCommentDTO;
import fun.huixi.weiju.pojo.dto.appeal.SaveAppealCommentDTO;
import fun.huixi.weiju.pojo.entity.*;
import fun.huixi.weiju.pojo.vo.appeal.AppealCommentItemVO;
import fun.huixi.weiju.pojo.vo.appeal.AppealItemVO;
import fun.huixi.weiju.pojo.dto.appeal.PageQueryAppealDTO;
import fun.huixi.weiju.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 *  相关业务的实现类
 * @Author 叶秋 
 * @Date 2021/11/10 22:27
 * @param 
 * @return 
 **/
@Slf4j
@Service
public class AppealBusinessImpl implements AppealBusiness {

    @Resource
    private WjAppealTagService appealTagService;

    @Resource
    private WjAppealTagCenterService appealTagCenterService;

    @Resource
    private WjAppealEndorseService appealEndorseService;

    @Resource
    private WjAppealCommentService appealCommentService;

    @Resource
    private WjAppealService appealService;

    @Resource
    private WjUserService userService;


    /**
     * 根据诉求id查询对应的标签
     *
     * @param appealIds 诉求id
     * @return java.util.Map<java.lang.Integer, java.util.List < fun.huixi.weiju.pojo.entity.WjAppealTag>>
     * @Author 叶秋
     * @Date 2021/11/15 23:11
     **/
    @Override
    public Map<Integer, List<WjAppealTag>> queryAppealTagByAppealId(List<Integer> appealIds) {

        HashMap<Integer, List<WjAppealTag>> integerListHashMap = new HashMap<>(appealIds.size());

        // 诉求对应的标签
        List<WjAppealTagCenter> appealTagCenters = appealTagCenterService.lambdaQuery()
                .in(WjAppealTagCenter::getAppealId, appealIds)
                .list();
        Map<Integer, List<WjAppealTagCenter>> appealIdToTagCenterListMap =
                appealTagCenters.stream().collect(Collectors.groupingBy(WjAppealTagCenter::getAppealId));

        // 诉求标签
        Set<Integer> appealTagIds =
                appealTagCenters.stream().map(WjAppealTagCenter::getTagId).collect(Collectors.toSet());

        if(null==appealTagIds || appealTagIds.size() == 0){
            return integerListHashMap;
        }

        List<WjAppealTag> appealTagList = appealTagService.lambdaQuery()
                .in(WjAppealTag::getTagId, appealTagIds)
                .list();


        for (Integer appealId : appealIds) {

            List<WjAppealTagCenter> wjAppealTagCenters = appealIdToTagCenterListMap.get(appealId);

            if(null==wjAppealTagCenters || wjAppealTagCenters.size() == 0){
                integerListHashMap.put(appealId, new ArrayList<WjAppealTag>());
                continue;
            }

            // 这个帖子 所属的标签id
            List<Integer> tagIds = wjAppealTagCenters.stream().map(WjAppealTagCenter::getTagId).collect(Collectors.toList());
            List<WjAppealTag> collect = appealTagList.stream()
                    .filter(item -> tagIds.contains(item.getTagId())).collect(Collectors.toList());

            integerListHashMap.put(appealId, collect);


        }
        


        return integerListHashMap;
    }

    /**
     * 分页查询诉求
     *
     * @param userId            查询人id
     * @param pageQueryAppealDTO 查询参数
     * @return fun.huixi.weiju.page.PageData<fun.huixi.weiju.pojo.vo.appeal.AppealItemVO>
     * @Author 叶秋
     * @Date 2021/11/15 22:11
     **/
    @Override
    public PageData<AppealItemVO> pageQueryAppeal(Integer userId, PageQueryAppealDTO pageQueryAppealDTO) {

        PageData<AppealItemVO> pageData = new PageData<>();

        Integer current = pageQueryAppealDTO.getCurrent();
        Integer size = pageQueryAppealDTO.getSize();
        BigDecimal latitude = pageQueryAppealDTO.getLatitude();
        BigDecimal longitude = pageQueryAppealDTO.getLongitude();


        // TODO: 2021/11/15 根据附近查询 之后加

        // 分页查询
        Page<WjAppeal> page = appealService.lambdaQuery()
                .page(new Page<>(current, size));
        BeanUtil.copyProperties(page, pageData);

        if(page.getTotal() == 0){
            return pageData;
        }

        // 查询用户信息
        Set<Integer> userIdSet = page.getRecords().stream().map(WjAppeal::getUserId).collect(Collectors.toSet());
        Map<Integer, WjUser> userIdTOUserInfoMap = userService.queryUserInfoByUserIds(userIdSet);

        // 查询自己是否点赞了该诉求
        List<Integer> appealIdList = page.getRecords().stream().map(WjAppeal::getAppealId).collect(Collectors.toList());
        Map<Integer, Boolean>  userIdToEndorseMap = new HashMap<>(appealIdList.size());
        if(userId!=null){
            userIdToEndorseMap = appealEndorseService.queryUserOrEndorseByUserId(userId, appealIdList);
        }

        // 帖子的标签
        Map<Integer, List<WjAppealTag>> appealIdToTagListMap = this.queryAppealTagByAppealId(appealIdList);


        // 循环组装参数
        ArrayList<AppealItemVO> appealItemVOS = new ArrayList<>();
        Map<Integer, Boolean> finalUserIdToEndorseMap = userIdToEndorseMap;
        page.getRecords().stream().forEach(item -> {

            AppealItemVO appealItemVO = new AppealItemVO();
            BeanUtil.copyProperties(item, appealItemVO);

            // 帖子标签
            if(null!=appealIdToTagListMap && appealIdToTagListMap.size()!=0){
                List<WjAppealTag> wjAppealTags = appealIdToTagListMap.get(item.getAppealId());
                appealItemVO.setTagList(wjAppealTags);
            }


            // 用户信息
            WjUser wjUser = userIdTOUserInfoMap.get(item.getUserId());
            BeanUtil.copyProperties(wjUser, appealItemVO);

            // 是否点赞
            if(null!=userId){
                Boolean orEndorse = finalUserIdToEndorseMap.get(item.getAppealId());
                appealItemVO.setOrEndorse(orEndorse);
            }

            appealItemVOS.add(appealItemVO);

        });

        pageData.setRecords(appealItemVOS);
        return pageData;
    }

    /**
     * 诉求点赞
     *
     * @param userId   用户id
     * @param appealId 诉求id
     * @return void
     * @Author 叶秋
     * @Date 2021/11/16 11:26
     **/
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void endorseAppeal(Integer userId, Integer appealId) {

        appealEndorseService.endorseAppeal(userId, appealId);

        // 点赞成功后增加帖子的点赞数量
        WjAppeal appeal = appealService.lambdaQuery()
                .select(WjAppeal::getAppealId, WjAppeal::getEndorseCount)
                .eq(WjAppeal::getAppealId, appealId)
                .one();
        appeal.setEndorseCount(appeal.getEndorseCount() + 1);

        boolean b = appealService.updateById(appeal);
        if(!b){
            log.error("用户点赞失败 修改帖子点赞数量时失败");
            throw new BusinessException("点赞失败");
        }

    }

    /**
     * 取消诉求点赞
     *
     * @param userId   用户id
     * @param appealId 诉求id
     * @return void
     * @Author 叶秋
     * @Date 2021/11/16 11:26
     **/
    @Override
    public void cancelEndorseAppeal(Integer userId, Integer appealId) {

        appealEndorseService.cancelEndorseAppeal(userId, appealId);

        // 点赞成功后增加帖子的点赞数量
        WjAppeal appeal = appealService.lambdaQuery()
                .select(WjAppeal::getAppealId, WjAppeal::getEndorseCount)
                .eq(WjAppeal::getAppealId, appealId)
                .one();
        appeal.setEndorseCount(appeal.getEndorseCount() -1);

        boolean b = appealService.updateById(appeal);
        if(!b){
            log.error("用户取消点赞失败 修改帖子点赞数量时失败");
            throw new BusinessException("取消点赞失败");
        }

    }

    /**
     * 保存帖子评论
     *
     * @param userId               用户id
     * @param saveAppealCommentDTO 保存参数
     * @return void
     * @Author 叶秋
     * @Date 2021/11/16 11:38
     **/
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveAppealComment(Integer userId, SaveAppealCommentDTO saveAppealCommentDTO) {

        Integer appealId = saveAppealCommentDTO.getAppealId();

        // 保存评论
        appealCommentService.saveAppealComment(userId, saveAppealCommentDTO);

        // 增加帖子的评论数量
        WjAppeal appeal = appealService.lambdaQuery()
                .select(WjAppeal::getAppealId, WjAppeal::getCommentCount)
                .eq(WjAppeal::getAppealId, appealId)
                .one();
        appeal.setCommentCount(appeal.getCommentCount() + 1);

        boolean b = appealService.updateById(appeal);
        if(!b){
            log.error("用户评论帖子 修改帖子评论数量时失败");
            throw new BusinessException("评论诉求失败");
        }


    }

    /**
     * 分页查询诉求的评论
     *
     * @param userId                    用户id
     * @param pageQueryAppealCommentDTO 分页查询参数
     * @return fun.huixi.weiju.page.PageData<fun.huixi.weiju.pojo.vo.appeal.AppealCommentItemVO>
     * @Author 叶秋
     * @Date 2021/11/16 11:55
     **/
    @Override
    public PageData<AppealCommentItemVO> pageQueryAppealComment(Integer userId, PageQueryAppealCommentDTO pageQueryAppealCommentDTO) {

        PageData<AppealCommentItemVO> pageData = new PageData<>();

        Integer appealId = pageQueryAppealCommentDTO.getAppealId();
        Integer current = pageQueryAppealCommentDTO.getCurrent();
        Integer size = pageQueryAppealCommentDTO.getSize();

        Page<WjAppealComment> page = appealCommentService.lambdaQuery()
                .eq(WjAppealComment::getAppealId, appealId)
                .page(new Page<>(current, size));
        BeanUtil.copyProperties(page, pageData);

        if(page.getTotal() == 0){
            return pageData;
        }

        // 查询评论对应的用户信息
        Set<Integer> userIdSet = page.getRecords().stream().map(WjAppealComment::getUserId).collect(Collectors.toSet());
        Map<Integer, WjUser> userIdToUserInfoMap = userService.queryUserInfoByUserIds(userIdSet);


        ArrayList<AppealCommentItemVO> appealCommentItemVOS = new ArrayList<>();
        page.getRecords().stream().forEach(item -> {

            AppealCommentItemVO appealCommentItemVO = new AppealCommentItemVO();
            BeanUtil.copyProperties(item, appealCommentItemVO);

            // 赋值用户信息
            WjUser wjUser = userIdToUserInfoMap.get(item.getUserId());
            appealCommentItemVO.setNickName(wjUser.getNickName());
            appealCommentItemVO.setHeadPortrait(wjUser.getHeadPortrait());

            appealCommentItemVOS.add(appealCommentItemVO);

        });

        pageData.setRecords(appealCommentItemVOS);
        return pageData;
    }
}
